#ifndef MyController_hpp
#define MyController_hpp
#include <dto/graph.hpp>
#include "dto/DTOs.hpp"
extern Graph g;
#include "oatpp/web/server/api/ApiController.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/macro/component.hpp"


#include OATPP_CODEGEN_BEGIN(ApiController) //<-- Begin Codegen

/**
 * Sample Api Controller.
 */
class MyController : public oatpp::web::server::api::ApiController {
public:
  /**
   * Constructor with object mapper.
   * @param objectMapper - default object mapper used to serialize/deserialize DTOs.
   */
  MyController(OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper))
    : oatpp::web::server::api::ApiController(objectMapper)
  {}
public:


  ENDPOINT("GET", "/", root) {

    auto dto = MyDto::createShared();
    dto->statusCode = 200;
    dto->message = "Hello World! Hello gcc";
    return createDtoResponse(Status::CODE_200, dto);
  }

    ADD_CORS(getUserById)
    ENDPOINT("GET", "/users/{userId}", getUserById,
             PATH(Int64, userId))
    {
        OATPP_LOGD("Test", "userId=%d", userId.getValue(6));
        return createResponse(Status::CODE_200, "everything is OK");
    }

    ADD_CORS(getresultByNodes)
    ENDPOINT("GET", "/graph/getNodes/{source}/{target}",getresultByNodes,
             PATH(String, source),PATH(String,target))
    {
        OATPP_LOGD("Test", "source=%s/targetId=%s", source.get(),target.get());
        map<NodePair, EdgeData*> targetEdgeInfo;
        int s,t;
        s=g.getIdByName( source);
        t=g.getIdByName(target);
        string st="[{\"source\":"+std::to_string(s)+",\"target\":"+std::to_string(t)+"}]";
        collectTargerInfo(s,t,g,targetEdgeInfo);
        auto dto = MyDto::createShared();
        dto->statusCode = 200;
        dto->sourceTarget=st;
        string a="[";
        string nodes="[";
      /*  for(auto it=g.id2Node.begin();it!=g.id2Node.end();it++)
        {
            if(it!=--g.id2Node.end())
                nodes+="{'name':"+std::to_string(it->first)+",'id':"+std::to_string(it->first)+"},";
            else{
                nodes+="{'name':"+std::to_string(it->first)+",'id':"+std::to_string(it->first)+"}";
            }
        }*/
        set<int>ns;
        for(auto it=targetEdgeInfo.begin();it!=targetEdgeInfo.end();it++)
        {
            ns.insert(it->first.s->id);
            ns.insert(it->first.t->id);
        }
        for(auto it=ns.begin();it!=ns.end();it++)
        {

            if(it!=--ns.end())
                nodes+="{\"name\":\""+g.id2Node[*it]->ndata->i+"\",\"id\":"+std::to_string(g.id2Node[*it]->id)+"},";
            else{
                nodes+="{\"name\":\""+g.id2Node[*it]->ndata->i+"\",\"id\":"+std::to_string(g.id2Node[*it]->id)+"}";
            }
        }
        nodes+="]";
        for(auto it=targetEdgeInfo.begin();it!=targetEdgeInfo.end();it++)
        {
            if(it!=--targetEdgeInfo.end())
                a+="{'source':"+std::to_string(it->first.s->id)+",'target':"+std::to_string(it->first.t->id)+
                   ",'type':\""+it->second->weight+"\"},";
            else{
                a+="{'source':"+std::to_string(it->first.s->id)+",'target':"+std::to_string(it->first.t->id)+
                   ",'type':\""+it->second->weight+"\"}";
            }
        }
        a+="]";
        dto->message=a;
        dto->nodes=nodes;
        return createDtoResponse(Status::CODE_200, dto);
    }

    ADD_CORS(getNeighborNodes)
    ENDPOINT("GET", "/graph/getNeighbors/{inputN}/{flag}",getNeighborNodes,
             PATH(String, inputN),PATH(String,flag))
    {
        OATPP_LOGD("Test", "Node=%s/flagId=%s", inputN.get(),flag.get());
        auto dto = MyDto::createShared();
        int n=g.getIdByName(inputN);
        string st="[{\"source\":"+std::to_string(n)+",\"target\":"+"-1}]";
        dto->statusCode = 200;
        dto->sourceTarget=st;
        string neighbors="[";
        string a="[";
        vector<Neighbor*>ns;
        Node *curnode=g.id2Node[n];
        if(flag=="in") {
            ns=g.getInNeighborList(curnode);
        }
        else{
            ns=g.getOutNeighborList(curnode);
        }
        neighbors+="{\"name\":\""+g.deescapeURL(inputN)+"\",\"id\":"+std::to_string(n)+"},";
        for(int i=0;i<ns.size();i++)
        {

            if(i!=ns.size()-1)
            {
                neighbors+="{\"name\":\""+ns[i]->neighbor->ndata->i+"\",\"id\":"+std::to_string(ns[i]->neighbor->id)+"},";
                if(flag=="out")
                a+="{'source':"+std::to_string(n)+",'target':"+std::to_string(ns[i]->neighbor->id)+
                   ",'type':\""+ns[i]->edgeData->weight+"\"},";
                else{
                    a+="{'target':"+std::to_string(n)+",'source':"+std::to_string(ns[i]->neighbor->id)+
                       ",'type':\""+ns[i]->edgeData->weight+"\"},";
                }
            }
            else{
                neighbors+="{\"name\":\""+ns[i]->neighbor->ndata->i+"\",\"id\":"+std::to_string(ns[i]->neighbor->id)+"}";
                if(flag=="out")
                a+="{'source':"+std::to_string(n)+",'target':"+std::to_string(ns[i]->neighbor->id)+
                   ",'type':\""+ns[i]->edgeData->weight+"\"}";
                else{
                    a+="{'target':"+std::to_string(n)+",'source':"+std::to_string(ns[i]->neighbor->id)+
                       ",'type':\""+ns[i]->edgeData->weight+"\"}";
                }
            }
        }
        neighbors+="]";
        a+="]";
        dto->message=a;
        dto->nodes=neighbors;
        return createDtoResponse(Status::CODE_200, dto);
    }

    ADD_CORS(getNodes)
    ENDPOINT("GET", "/graph/getNodes", getNodes)
    {
        map<NodePair, EdgeData*> targetEdgeInfo;
        int s,t;
        s=265;
        t=462;
        collectTargerInfo(s,t,g,targetEdgeInfo);
        auto dto = MyDto::createShared();
        dto->statusCode = 200;
        string a="[";
        string nodes="[";
       /* for(auto it=g.id2Node.begin();it!=g.id2Node.end();it++)
        {
            if(it!=--g.id2Node.end())
                nodes+="{'name':"+std::to_string(it->first)+",'id':"+std::to_string(it->first)+"},";
            else{
                nodes+="{'name':"+std::to_string(it->first)+",'id':"+std::to_string(it->first)+"}";
            }
        }*/
        set<int>ns;
        for(auto it=targetEdgeInfo.begin();it!=targetEdgeInfo.end();it++)
        {
            ns.insert(it->first.s->id);
            ns.insert(it->first.t->id);
        }
        for(auto it=ns.begin();it!=ns.end();it++)
        {

            if(it!=--ns.end())
                nodes+="{\"name\":\""+g.id2Node[*it]->ndata->i+"\",\"id\":"+std::to_string(g.id2Node[*it]->id)+"},";
            else{
                nodes+="{\"name\":\""+g.id2Node[*it]->ndata->i+"\",\"id\":"+std::to_string(g.id2Node[*it]->id)+"}";
            }
        }
        nodes+="]";
        for(auto it=targetEdgeInfo.begin();it!=targetEdgeInfo.end();it++)
        {
            if(it!=--targetEdgeInfo.end())
            a+="{'source':"+std::to_string(it->first.s->id)+",'target':"+std::to_string(it->first.t->id)+
                    ",'type':\""+=it->second->weight+"\"},";
            else{
                a+="{'source':"+std::to_string(it->first.s->id)+",'target':"+std::to_string(it->first.t->id)+
                   ",'type':\""+it->second->weight+"\"}";
            }
        }
        a+="]";
        dto->message=a;
        dto->nodes=nodes;
        return createDtoResponse(Status::CODE_200, dto);
    }
  // TODO Insert Your endpoints here !!!
  
};

#include OATPP_CODEGEN_END(ApiController) //<-- End Codegen

#endif /* MyController_hpp */
